﻿using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Net;
using System.Reflection;
using System.Security.Principal;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Windows.Forms;

namespace __ts.Core.Utilities
{
    /// <summary>
    /// 
    /// </summary>
    public static class Util
    {
        public static bool IsRuningWithAdministrator()
        {
            WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
            return principal.IsInRole(WindowsBuiltInRole.Administrator);
        }

        static readonly DateTime unixTPStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static long toUTP(DateTime dt)
        {
            TimeSpan toNow = dt.Subtract(unixTPStart);
            return (long)Math.Round(toNow.TotalMilliseconds);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="tp"></param>
        /// <returns></returns>
        public static DateTime fromUTP(long tp)
        {
            return unixTPStart.Add(new TimeSpan(tp * 10000000));
        }
        /// <summary>
        /// 
        /// </summary>
        public static string RootPath
        {
            get
            {
                if (HttpContext.Current != null)
                    return HttpContext.Current.Request.PhysicalApplicationPath.TrimEnd('\\');
                else
                    return Application.StartupPath.TrimEnd('\\');
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sr"></param>
        /// <param name="para"></param>
        /// <param name="po"></param>
        public static void RetreiveParameters(ref StreamReader sr, ParameterInfo[] para, ref object[] po)
        {
            for (int i = 0; i < para.Length; i++)
            {
                po[i] = para[i].DefaultValue;
            }
            Hashtable ht = new Hashtable();
            try
            {
                string line = sr.ReadLine();
                string[] arrParam = line.Split('&');
                string key, value;
                string param = null;

                foreach (string p in arrParam)
                {
                    param = p.Replace("%26", "%").Replace("%3D", "=");

                    key = null;
                    for (int i = 0; i < para.Length; i++)
                    {
                        if (param.StartsWith(para[i].Name + "="))
                        {
                            key = para[i].Name;
                            break;
                        }
                    }

                    // Ok, we found a new argument.
                    if (key != null)
                    {
                        value = param.Substring(key.Length + 1);
                        //value = HttpUtility.UrlDecode(value);
                        ht.Add(key, value);
                    }
                }
            }
            catch (Exception) { }
            finally
            {
                sr.Close();
            }

            for (int i = 0; i < para.Length; i++)
            {
                if (ht[para[i].Name] != null)
                {
                    po[i] = FromString(ht[para[i].Name].ToString(), para[i].ParameterType);
                }
            }
        }
        private static object FromString(string s, Type t)
        {
            if (s == null || (s == "null" && t != typeof(String)))
            {
                return null;
            }

            if (t == typeof(String))
            {
                return s;
            }
            else if (t == typeof(Int16))
            {
                return Convert.ToInt16(s);
            }
            else if (t == typeof(Int32))
            {
                return Convert.ToInt32(s);
            }
            else if (t == typeof(Int64))
            {
                return Convert.ToInt64(s);
            }
            else if (t == typeof(Double))
            {
                return Convert.ToDouble(s.Replace(".", CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator));
            }
            else if (t == typeof(Single))
            {
                return Convert.ToSingle(s.Replace(".", CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator));
            }
            else if (t == typeof(Decimal))
            {
                return Convert.ToDecimal(s.Replace(".", CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator));
            }
            else if (t == typeof(Boolean))
            {
                return bool.Parse(s.ToLower());
            }
            else if (t == typeof(bool[]))
            {
                string[] ss = s.Split(',');
                bool[] sb = new bool[ss.Length];

                for (int i = 0; i < ss.Length; i++)
                {
                    sb[i] = bool.Parse(ss[i].ToLower());
                }

                return sb;
            }
            else if (t == typeof(Int16[]))
            {
                string[] ss = s.Split(',');
                Int16[] si = new Int16[ss.Length];
                for (int i = 0; i < ss.Length; i++)
                {
                    si[i] = Int16.Parse(ss[i]);
                }

                return si;
            }
            else if (t == typeof(Int32[]))
            {
                string[] ss = s.Split(',');
                Int32[] si = new Int32[ss.Length];
                for (int i = 0; i < ss.Length; i++)
                {
                    si[i] = Int32.Parse(ss[i]);
                }

                return si;
            }
            else if (t == typeof(Int64[]))
            {
                string[] ss = s.Split(',');
                Int64[] si = new Int64[ss.Length];
                for (int i = 0; i < ss.Length; i++)
                {
                    si[i] = Int64.Parse(ss[i]);
                }

                return si;
            }
            else if (t == typeof(Double[]))
            {
                string[] ss = s.Split(',');
                Double[] si = new Double[ss.Length];
                for (int i = 0; i < ss.Length; i++)
                {
                    si[i] = Double.Parse(ss[i].Replace(".", CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator));
                }

                return si;
            }
            else if (t == typeof(Single[]))
            {
                string[] ss = s.Split(',');
                Single[] si = new Single[ss.Length];
                for (int i = 0; i < ss.Length; i++)
                {
                    si[i] = Single.Parse(ss[i].Replace(".", CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator));
                }

                return si;
            }
            else if (t == typeof(Decimal[]))
            {
                string[] ss = s.Split(',');
                Decimal[] si = new Decimal[ss.Length];
                for (int i = 0; i < ss.Length; i++)
                {
                    si[i] = Decimal.Parse(ss[i].Replace(".", CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator));
                }

                return si;
            }
            else if (t == typeof(string[]) && s.StartsWith("[") && s.EndsWith("]"))
            {
                s = s.Substring(1, s.Length - 2);

                Regex rex = new Regex(
                    // match quoted text if possible
                    // otherwise match until a comma is found
                    @"  ""[^\\""]*""  |  [^,]+  ",
                    RegexOptions.IgnorePatternWhitespace);

                string[] r = new string[rex.Matches(s).Count];

                int i = 0;
                foreach (Match m in rex.Matches(s))
                {
                    r[i++] = m.Value.Substring(1, m.Value.Length - 2);
                }
                return r;
            }

            // TODO: 
            throw new NotImplementedException();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="host"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public static IPEndPoint GetEndPoint(string host, int port)
        {
            IPAddress ipAddress;
            IPAddress.TryParse(host, out ipAddress);
            if (ipAddress == null)
            {
                try
                {
                    System.Net.IPHostEntry ipHostEntry = System.Net.Dns.GetHostEntry(host);
                    ipAddress = ipHostEntry.AddressList[0];
                }
                catch { }
            }
            return new IPEndPoint(ipAddress, port);
        }
        /// <summary>
        /// 
        /// </summary>
        public const String CHARSET_DEFAULT = "utf-8";
        /// <summary>
        /// 
        /// </summary>
        public const int LENGTH_KEY = 16;
        static Encoding DefaultEncoding = Encoding.GetEncoding(CHARSET_DEFAULT);
        static DateTime baseDateTime = DateTime.Parse("1970-1-01 00:00:00.000");
        /// <summary>
        /// 
        /// </summary>
        public static Random Random = new Random();

        /// <summary>
        /// 把字节数组从offset开始的len个字节转换成一个unsigned int，
        /// </summary>
        /// <param name="inData">字节数组</param>
        /// <param name="offset">从哪里开始转换.</param>
        /// <param name="len">转换长度, 如果len超过8则忽略后面的.</param>
        /// <returns></returns>
        public static uint GetUInt(byte[] inData, int offset, int len)
        {
            uint ret = 0;
            int end = 0;
            if (len > 8)
                end = offset + 8;
            else
                end = offset + len;
            for (int i = 0; i < end; i++)
            {
                ret <<= 8;
                ret |= (uint)inData[i];
            }
            return ret;
        }
        /// <summary>
        /// 根据某种编码方式将字节数组转换成字符串
        /// </summary>
        /// <param name="b">字节数组</param>
        /// <param name="encoding">encoding 编码方式</param>
        /// <returns> 如果encoding不支持，返回一个缺省编码的字符串</returns>
        public static string GetString(byte[] b, string encoding)
        {
            if (b == null)
                return null;
            try
            {
                return Encoding.GetEncoding(encoding).GetString(b);
            }
            catch
            {
                return Encoding.Default.GetString(b);
            }
        }

        /// <summary>
        /// 根据缺省编码将字节数组转换成字符串
        /// </summary>
        /// <param name="b">字节数组</param>
        /// <returns>字符串</returns>
        public static string GetString(byte[] b)
        {
            return GetString(b, CHARSET_DEFAULT);
        }
        /// <summary>
        /// * 从buf的当前位置解析出一个字符串，直到碰到了buf的结尾
        /// * <p>
        /// * 此方法不负责调整buf位置，调用之前务必使buf当前位置处于字符串开头。在读取完成
        /// * 后，buf当前位置将位于buf最后之后
        /// * </p>
        /// * <p>
        /// * 返回的字符串将使用QQ缺省编码，一般来说就是GBK编码
        /// </summary>
        /// <param name="buf">The buf.</param>
        /// <returns></returns>
        public static string GetString(ByteBuffer buf)
        {
            ByteBuffer temp = new ByteBuffer();
            while (buf.HasRemaining())
            {
                temp.Put(buf.Get());
            }
            return GetString(temp.ToByteArray());
        }
        /// <summary>
        /// 从buf的当前位置解析出一个字符串，直到碰到了buf的结尾或者读取了len个byte之后停止
        /// 此方法不负责调整buf位置，调用之前务必使buf当前位置处于字符串开头。在读取完成
        /// * 后，buf当前位置将位于len字节之后或者最后之后
        /// </summary>
        /// <param name="buf"></param>
        /// <param name="len"></param>
        /// <returns></returns>
        public static string GetString(ByteBuffer buf, int len)
        {
            ByteBuffer temp = new ByteBuffer();
            while (buf.HasRemaining() && len-- > 0)
            {
                temp.Put(buf.Get());
            }
            return GetString(temp.ToByteArray());
        }
        /// <summary>
        /// * 从buf的当前位置解析出一个字符串，直到碰到了delimit或者读取了maxLen个byte或者
        /// * 碰到结尾之后停止
        /// *此方法不负责调整buf位置，调用之前务必使buf当前位置处于字符串开头。在读取完成
        /// *后，buf当前位置将位于maxLen之后
        /// </summary>
        /// <param name="buf">The buf.</param>
        /// <param name="delimit">The delimit.</param>
        /// <param name="maxLen">The max len.</param>
        /// <returns></returns>
        public static String GetString(ByteBuffer buf, byte delimit, int maxLen)
        {
            ByteBuffer temp = new ByteBuffer();
            while (buf.HasRemaining() && maxLen-- > 0)
            {
                byte b = buf.Get();
                if (b == delimit)
                    break;
                else
                    temp.Put(b);
            }
            while (buf.HasRemaining() && maxLen-- > 0)
                buf.Get();
            return GetString(temp.ToByteArray());
        }
        /// <summary>
        /// 根据某种编码方式将字节数组转换成字符串
        /// </summary>
        /// <param name="b">The b.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="len">The len.</param>
        /// <returns></returns>
        public static string GetString(byte[] b, int offset, int len)
        {
            byte[] temp = new byte[len];
            Array.Copy(b, offset, temp, 0, len);
            return GetString(temp);
        }
        /// <summary>
        /// 从buf的当前位置解析出一个字符串，直到碰到一个分隔符为止，或者到了buf的结尾
        /// 此方法不负责调整buf位置，调用之前务必使buf当前位置处于字符串开头。在读取完成
        /// * 后，buf当前位置将位于分隔符之后
        /// </summary>
        /// <param name="buf">The buf.</param>
        /// <param name="delimit">The delimit.</param>
        /// <returns></returns>
        public static string GetString(ByteBuffer buf, byte delimit)
        {
            ByteBuffer temp = new ByteBuffer();
            while (buf.HasRemaining())
            {
                byte b = buf.Get();
                if (b == delimit)
                    return GetString(temp.ToByteArray());
                else
                    temp.Put(b);
            }
            return GetString(temp.ToByteArray());
        }
        /// <summary>
        /// 把字符串转换成int
        /// </summary>
        /// <param name="s">字符串</param>
        /// <param name="defaultValue">如果转换失败，返回这个值</param>
        /// <returns></returns>
        public static int GetInt(string s, int defaultValue)
        {
            int value;
            if (int.TryParse(s, out value))
            {
                return value;
            }
            else
            {
                return defaultValue;
            }
        }
        /// <summary>
        /// 字符串转二进制字数组
        /// </summary>
        /// <param name="s">The s.</param>
        /// <returns></returns>
        public static byte[] GetBytes(string s)
        {
            return DefaultEncoding.GetBytes(s);
        }
        /// <summary>
        /// 一个随机产生的密钥字节数组
        /// </summary>
        /// <returns></returns>
        public static byte[] RandomKey()
        {
            byte[] key = new byte[LENGTH_KEY];
            (new Random()).NextBytes(key);
            return key;
        }
        /// <summary>
        /// 用于代替 System.currentTimeMillis()
        /// </summary>
        /// <param name="dateTime">The date time.</param>
        /// <returns></returns>
        public static long GetTimeMillis(DateTime dateTime)
        {
            return (long)(dateTime - baseDateTime).TotalMilliseconds;
        }
        /// <summary>
        /// 根据服务器返回的毫秒表示的日期，获得实际的日期
        /// Gets the date time from millis.
        /// 似乎服务器返回的日期要加上8个小时才能得到正确的 +8 时区的登录时间
        /// </summary>
        /// <param name="millis">The millis.</param>
        /// <returns></returns>
        public static DateTime GetDateTimeFromMillis(long millis)
        {
            return baseDateTime.AddTicks(millis * TimeSpan.TicksPerMillisecond).AddHours(8);
        }
        /// <summary>
        /// 判断IP是否全0
        /// </summary>
        /// <param name="ip">The ip.</param>
        /// <returns></returns>
        public static bool IsIPZero(byte[] ip)
        {
            for (int i = 0; i < ip.Length; i++)
            {
                if (ip[i] != 0)
                    return false;
            }
            return true;
        }
        /// <summary>
        /// ip的字节数组形式转为字符串形式的ip
        /// </summary>
        /// <param name="ip">The ip.</param>
        /// <returns></returns>
        public static String GetIpStringFromBytes(byte[] ip)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(ip[0] & 0xFF);
            sb.Append('.');
            sb.Append(ip[1] & 0xFF);
            sb.Append('.');
            sb.Append(ip[2] & 0xFF);
            sb.Append('.');
            sb.Append(ip[3] & 0xFF);
            return sb.ToString();
        }
        /// <summary>
        /// 转为16进制字符串
        /// </summary>
        /// <param name="bs">The bs.</param>
        /// <returns></returns>
        public static string ToHex(byte[] bs)
        {
            StringBuilder sb = new StringBuilder();
            foreach (byte b in bs)
            {
                sb.Append(b.ToString("x") + " ");
            }
            return sb.Remove(sb.Length - 1, 1).ToString();
        }
        /// <summary>
        /// 从字节数组的指定位置起的len的字节转换成int型(big-endian)，如果不足4字节，高位认为是0
        /// </summary>
        /// <param name="b">字节数组</param>
        /// <param name="offset">转换起始位置</param>
        /// <param name="len">转换长度</param>
        /// <returns>转换后的int</returns>
        public static int GetIntFromBytes(byte[] b, int offset, int len)
        {
            if (len > 4)
                len = 4;

            int ret = 0;
            int end = offset + len;
            for (int i = offset; i < end; i++)
            {
                ret |= b[i] & 0xFF;
                if (i < end - 1)
                    ret <<= 8;
            }
            return ret;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string GetMd5(string path)
        {
            try
            {
                //定义流
                FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
                //定义MD5加密算法
                System.Security.Cryptography.MD5CryptoServiceProvider get_md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                byte[] hash_byte = get_md5.ComputeHash(fs);
                string resule = System.BitConverter.ToString(hash_byte);
                resule = resule.Replace("-", "");
                fs.Flush();
                fs.Close();
                return resule;
            }
            catch (Exception)
            {
                return null;
            }
        }
    }
}
